{% import "utils.inc.jinja" as utils %}
{{- utils.do_not_edit() }}
// This file was generated from {{ proto.source_file }}
#include "{{ proto.source_file_without_ext }}_service.usrv.pb.hpp"

{# All constant includes must go inside this header #}
#include <userver/ugrpc/impl/protobuf_collector.hpp>
#include <userver/ugrpc/server/impl/codegen_definitions.hpp>

{{ utils.include_grpcpp(proto.source_file_without_ext) }}

{% call utils.optional_namespace(proto.namespace) %}

{% for service in proto.services %}

// Inline to deduplicate between client.usrv.cpp and service.usrv.cpp
inline constexpr std::string_view k{{service.name}}MethodNames[] = {
  {% for method in service.method %}
  "{{proto.package_prefix}}{{service.name}}/{{method.name}}",
  {% endfor %}
};

// Inline to deduplicate between client.usrv.cpp and service.usrv.cpp
inline const bool k{{service.name}}TypesRegistration =
    (USERVER_NAMESPACE::ugrpc::impl::RegisterMessageTypes({
      {% for method in service.method %}
        std::string("{{method.input_type}}").substr(1),
        std::string("{{method.output_type}}").substr(1),
      {% endfor %}
    }),
    false);

{% for method in service.method %}
{% if method.client_streaming and method.server_streaming %}

{{service.name}}Base::{{method.name}}Result {{service.name}}Base::{{method.name}}(
    [[maybe_unused]] CallContext& context,
    [[maybe_unused]] {{method.name}}ReaderWriter& stream) {
  UASSERT_MSG(false, "Called not implemented {{proto.package_prefix}}{{service.name}}/{{method.name}}");
  return USERVER_NAMESPACE::ugrpc::server::impl::kUnimplementedStatus;
}

// Legacy
void {{service.name}}Base::{{method.name}}({{method.name}}Call& call) {
  CallContext context{call};
  auto result = {{method.name}}(context, call);
  USERVER_NAMESPACE::ugrpc::server::impl::Finalize(call, std::move(result));
}

{% elif method.client_streaming %}

{{service.name}}Base::{{method.name}}Result {{service.name}}Base::{{method.name}}(
    [[maybe_unused]] CallContext& context,
    [[maybe_unused]] {{method.name}}Reader& reader) {
  UASSERT_MSG(false, "Called not implemented {{proto.package_prefix}}{{service.name}}/{{method.name}}");
  return USERVER_NAMESPACE::ugrpc::server::impl::kUnimplementedStatus;
}

// Legacy
void {{service.name}}Base::{{method.name}}({{method.name}}Call& call) {
  CallContext context{call};
  auto result = {{method.name}}(context, call);
  USERVER_NAMESPACE::ugrpc::server::impl::Finalize(call, std::move(result));
}

{% elif method.server_streaming %}

{{service.name}}Base::{{method.name}}Result {{service.name}}Base::{{method.name}}(
    [[maybe_unused]] CallContext& context,
    [[maybe_unused]] {{ method.input_type | grpc_to_cpp_name }}&& request,
    [[maybe_unused]] {{method.name}}Writer& writer) {
  UASSERT_MSG(false, "Called not implemented {{proto.package_prefix}}{{service.name}}/{{method.name}}");
  return USERVER_NAMESPACE::ugrpc::server::impl::kUnimplementedStatus;
}

// Legacy
void {{service.name}}Base::{{method.name}}({{method.name}}Call& call,
                                           {{ method.input_type | grpc_to_cpp_name }}&& request) {
  CallContext context{call};
  auto result = {{method.name}}(context, std::move(request), call);
  USERVER_NAMESPACE::ugrpc::server::impl::Finalize(call, std::move(result));
}

{% else %}

{{service.name}}Base::{{method.name}}Result {{service.name}}Base::{{method.name}}(
    [[maybe_unused]] CallContext& context,
    [[maybe_unused]] {{ method.input_type | grpc_to_cpp_name }}&& request) {
  UASSERT_MSG(false, "Called not implemented {{proto.package_prefix}}{{service.name}}/{{method.name}}");
  return USERVER_NAMESPACE::ugrpc::server::impl::kUnimplementedStatus;
}

// Legacy
void {{service.name}}Base::{{method.name}}({{method.name}}Call& call,
                                           {{ method.input_type | grpc_to_cpp_name }}&& request) {
  CallContext context{call};
  auto result = {{method.name}}(context, std::move(request));
  USERVER_NAMESPACE::ugrpc::server::impl::Finalize(call, std::move(result));
}

{% endif %}
{% endfor %}

std::unique_ptr<USERVER_NAMESPACE::ugrpc::server::impl::ServiceWorker>
{{service.name}}Base::MakeWorker(
    USERVER_NAMESPACE::ugrpc::server::impl::ServiceSettings&& settings) {
  (void)k{{service.name}}TypesRegistration;  // odr-use

  return USERVER_NAMESPACE::ugrpc::server::impl::MakeServiceWorker<
      {{utils.namespace_with_colons(proto.namespace)}}::{{service.name}}>(
      std::move(settings), k{{service.name}}MethodNames, *this,
      {% for method in service.method %}
      USERVER_NAMESPACE::ugrpc::server::impl::Dispatch(
          &{{service.name}}Base::{{method.name}}){{ "," if not loop.last else ");" }}
      {% endfor %}
}

{% endfor %}

{% endcall %} {# utils.optional_namespace #}
